#include "burner.h"

#define MAX_VIDEO_BUFFER 2

static bool bVideoOkay = false;
static UINT8 *pDrawBuffers[MAX_VIDEO_BUFFER] = {0};
static INT32 nDrawBuffersPos = 0;

static void VideoBufferInit()
{
    nAudSegLen = (nBurnSoundRate * 100 + (nBurnFPS >> 1)) / nBurnFPS;
    nBurnSoundLen = nAudSegLen;

    size_t nSize = nBurnGameWidth * nBurnGameHeight * nBurnBpp;
    for (INT32 i = 0; i < MAX_VIDEO_BUFFER; i++)
    {
        pDrawBuffers[i] = (UINT8 *)malloc(nSize);
        if (pDrawBuffers[i])
            memset(pDrawBuffers[i], 0, nSize);
    }
    nDrawBuffersPos = 0;
    pBurnDraw = pDrawBuffers[nDrawBuffersPos];
}

static void VideoBufferDeinit()
{
    for (INT32 i = 0; i < MAX_VIDEO_BUFFER; i++)
    {
        if (pDrawBuffers[i])
            free(pDrawBuffers[i]);
        pDrawBuffers[i] = NULL;
    }
    nDrawBuffersPos = 0;
    pBurnDraw = NULL;
}

static enum retro_pixel_format GetPixelFormat()
{
    if (nBurnColorDepth == 15)
        return RETRO_PIXEL_FORMAT_0RGB1555;
    else if (nBurnColorDepth == 16)
        return RETRO_PIXEL_FORMAT_RGB565;
    else
        return RETRO_PIXEL_FORMAT_XRGB8888;
}

static UINT8 *GetFrameBuffer()
{
    struct retro_framebuffer fb = {0};

    fb.width = nBurnGameWidth;
    fb.height = nBurnGameHeight;
    fb.access_flags = RETRO_MEMORY_ACCESS_WRITE;

    if (environ_cb(RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER, &fb) && fb.format == GetPixelFormat())
        return (UINT8 *)fb.data;

    nDrawBuffersPos = (nDrawBuffersPos + 1) % MAX_VIDEO_BUFFER;
    return pDrawBuffers[nDrawBuffersPos];
}

UINT32 BurnUpdateDrawOut(UINT8 *pIn, UINT8 **pOut)
{
    if (bBurnDraw && pIn)
        video_cb(pIn, nBurnGameWidth, nBurnGameHeight, nBurnPitch);
    *pOut = GetFrameBuffer();

    return 0;
}

UINT32 BurnVideoOutInit()
{
    if (bVideoOkay)
        BurnVideoOutExit();

    VideoBufferInit();
    bVideoOkay = 1;

    return 0;
}

UINT32 BurnVideoOutExit()
{
    VideoBufferDeinit();
    bVideoOkay = 0;

    return 0;
}
